home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 10 / The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso / PC_SIGCD / 04 / 2 / DISK0427.ZIP / TIMER.PAS < prev    next >
Pascal/Delphi Source File  |  1985-05-28  |  5KB  |  121 lines

  1. {----------------------------------------------------------------------} 
  2. {                                                                      } 
  3. {  TIMER.INC - simple timer interrupt routine                          } 
  4. {  increments a counter 18.2 times a second                            } 
  5. {                                                                      } 
  6. {  This code is intended to be included within a larger program.       } 
  7. {  The main program must first call Timer_Init to initialize the       } 
  8. {  interrupt vector. Before terminating, Timer_Close must be called    } 
  9. {  to restore the interrupt vector contents.                           } 
  10. {  Timer_Counter contains the elapsed time and canbe interrogated and } 
  11. {  reset by the main routine.                                          } 
  12. {                                                                      } 
  13. {  This code is heavily dependant on the characteristics of the IBM PC } 
  14. {  and PC DOS release 2.0.                                             } 
  15. {                                                                      } 
  16. {  Michael Quinlan                                                     } 
  17. {                                                                      } 
  18. {----------------------------------------------------------------------} 
  19.  
  20. { CONST areas are used because on entry, the interrupt service routine 
  21.   only has the correct Code Segment; the Data Segment register value must 
  22.   be obtained from the Code Segment } 
  23.  
  24. const 
  25.   Timer_DSeg_Save : Integer = 0;  { save DS register in Code segment for ISR } 
  26.  
  27. const 
  28.   Timer_Vector = $1C;  { Interrupt vector for timer routine } 
  29.  
  30. const 
  31.   Timer_Old_Int : record  { area to save the old interrupt vector value } 
  32.                     o, s : integer 
  33.                   end = (o:0; s:0);  { must be in CODE segment for ISR } 
  34.  
  35. var 
  36.  Timer_Counter : Integer;  { counter incremented 18.2 times a second } 
  37.  
  38. var 
  39.   DOS_Regs : Record 
  40.                ax, bx, cx, dx, bp, si, di, ds, es, flag : integer 
  41.              end; 
  42.  
  43. procedure DOS_Set_Intrpt(v, s, o : integer); 
  44. { call PC DOS to set an interrupt vector } 
  45. begin 
  46.   with DOS_Regs do 
  47.     begin 
  48.       ax := $2500 + (v and $00FF); 
  49.       ds := s; 
  50.       dx := o; 
  51.       MsDos(DOS_Regs) 
  52.     end 
  53. end; { DOS_Set_Intrpt } 
  54.  
  55. procedure DOS_Get_Intrpt(v : integer; var s, o : integer); 
  56. { call PC DOS to get the value of an interrupt vector } 
  57. begin 
  58.   with DOS_Regs do 
  59.     begin 
  60.       ax := $3500 + (v and $00FF); 
  61.       MsDos(Dos_Regs); 
  62.       s := es; 
  63.       o := bx 
  64.     end 
  65. end; { DOS_Get_Intrpt } 
  66.  
  67. {----------------------------------------------------------------------} 
  68. {                                                                      } 
  69. {  TIMERISR -- PCDOS Timer Interrupt. Increments a counter 18.2 times  } 
  70. {  a second.                                                           } 
  71. {                                                                      } 
  72. {----------------------------------------------------------------------} 
  73.  
  74. procedure Timer_Isr; 
  75. begin 
  76.  
  77.     { on entry, Turbo Pascal has saved BP and SP on the stack } 
  78.     { the manual is incorrect } 
  79.  
  80.   Inline( 
  81.       { save all registers used } 
  82.     $50/                             { PUSH AX } 
  83.     $1E/                             { PUSH DS } 
  84.       { set up the DS register to point to the data segment } 
  85.     $2E/$FF/$36/Timer_DSeg_Save/     { PUSH CS:Timer_DSeg_Save } 
  86.     $1F/                             { POP DS } 
  87.     $FA/                             { CLI } 
  88.     $A1/Timer_Counter/               { MOV AX,Timer_Counter } 
  89.     $3D/MaxInt/                      { CMP AX,MaxInt } 
  90.     $74/$04/                         { JE L001 } 
  91.     $FF/$06/Timer_Counter/           { INC Timer_Counter } 
  92. {L001:} 
  93.     $FB/                             { STI } 
  94.       { invoke any other timer routines installed } 
  95.       { it will be her responsibility to issue the IRET } 
  96.       { restore the registers first } 
  97.     $1F/                             { POP DS } 
  98.     $58/                             { POP AX } 
  99.     $5C/                             { POP SP } 
  100.     $5D/                             { POP BP } 
  101.     $2E/$FF/$2E/Timer_Old_Int)       { JMP CS:Timer_Old_Int (cross-segment, 
  102.                                                              indirect) } 
  103. end; { Timer_Isr } 
  104.  
  105. procedure Timer_Init; 
  106. { install the timer interrupt } 
  107. begin 
  108.   Timer_DSeg_Save := DSeg;  { save DS register for ISR } 
  109.     { get the current contents of the timer interrupt vector } 
  110.     { the TIMER ISR will invoke this to finish any timer processing } 
  111.   DOS_Get_Intrpt(Timer_Vector, Timer_Old_Int.s, Timer_Old_Int.o); 
  112.     { begin executing the timer interrupt } 
  113.   DOS_Set_Intrpt(Timer_Vector, CSeg, Ofs(Timer_Isr)) 
  114. end; { Timer_Init } 
  115.  
  116. procedure Timer_Close; 
  117. { remove the timer interrupt } 
  118. begin
  119.   DOS_Set_Intrpt(Timer_Vector, Timer_Old_Int.s, Timer_Old_Int.o)
  120. end; { Timer_Close }
  121.     d